package com.mingyuean.demo.mybatis.mapping;

import com.mingyuean.demo.mybatis.transaction.TransactionFactory;

import javax.sql.DataSource;

/**
 * @author MingYueAn
 * <p>  Environment 类，用于封装 MyBatis 的环境信息。
 * <p>  2023/3/22 20:11
 * @version: 1.0
 */
public class Environment {

    /**
     * 环境id，用于标识该环境的唯一性
     */
    private final String id;
    /**
     * 事务工厂，用于根据指定的 JDBC 连接创建事务
     */
    private final TransactionFactory transactionFactory;
    /**
     * 数据源，包含了数据库的连接信息，用于获取 JDBC 连接
     */
    private final DataSource dataSource;

    /**
     * 构造方法，用于初始化 Environment 对象。
     *
     * @param id                 环境id，用于标识该环境的唯一性。
     * @param transactionFactory 事务工厂，用于根据指定的 JDBC 连接创建事务。
     * @param dataSource         数据源，包含了数据库的连接信息，用于获取 JDBC 连接。
     */
    public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
        this.id = id;
        this.transactionFactory = transactionFactory;
        this.dataSource = dataSource;
    }

    /**
     * <p>Environment 类的 Builder 内部类，用于实现构建器模式，方便构建 Environment 对象。
     * <p>建造者模式（Builder Pattern）
     * <p>使用建造者模式的原因是，在创建 Environment 类的实例时，需要传递三个参数，而这些参数都是必要的，并且顺序也固定，如果使用构造函数来创建实例，则容易出错。而使用建造者模式，则可以通过链式方法调用，按需设置属性，并且不易出错，更加灵活。
     * <p>Environment.Builder 类则用于构建 Environment 对象，实现了链式调用设置属性的方法，并提供了 build 方法来创建 Environment 实例。
     * <p>【与MappedStatement的对比】
     * <p>在使用上，如果一个对象需要设置大量属性，同时这些属性有一定的顺序依赖关系，那么使用构造函数可能不太方便，此时使用传统的 builder 模式即可；而如果属性比较少，而且可以不需要特定的顺序，则使用链式调用的 builder 模式更加简单明了。
     */
    public static class Builder {
        private String id;
        private TransactionFactory transactionFactory;
        private DataSource dataSource;

        /**
         * 构造方法，用于初始化 Builder 对象。
         *
         * @param id 环境id，用于标识该环境的唯一性
         */
        public Builder(String id) {
            this.id = id;
        }

        /**
         * 设置当前 Environment 对象的事务工厂属性。
         *
         * @param transactionFactory 事务工厂，用于根据指定的 JDBC 连接创建事务。
         * @return 返回当前 Builder 对象。
         */
        public Builder transactionFactory(TransactionFactory transactionFactory) {
            this.transactionFactory = transactionFactory;
            return this;
        }

        /**
         * 设置当前 Environment 对象的数据源属性。
         *
         * @param dataSource 数据源，包含了数据库的连接信息，用于获取 JDBC 连接。
         * @return 返回当前 Builder 对象。
         */
        public Builder dataSource(DataSource dataSource) {
            this.dataSource = dataSource;
            return this;
        }

        /**
         * 创建并返回 Environment 对象。
         *
         * @return 返回创建好的 Environment 对象。
         */
        public Environment build() {
            return new Environment(this.id, this.transactionFactory, this.dataSource);
        }
    }

    public String getId() {
        return id;
    }

    public TransactionFactory getTransactionFactory() {
        return transactionFactory;
    }

    public DataSource getDataSource() {
        return dataSource;
    }
}
